package com.xoms.front.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.xoms.front.aspect.datasource.DataSourceSwitcher;
import com.xoms.front.cache.dao.AccountCache;
import com.xoms.front.cache.dao.ResourceCache;
import com.xoms.front.constants.StringConstants;
import com.xoms.front.controller.res.bean.RAccountLoginBean;
import com.xoms.front.controller.res.bean.RHaveResourcesBean;
import com.xoms.front.controller.res.bean.RVertifyVCodeBean;
import com.xoms.front.model.AccountBean;
import com.xoms.front.model.res.HaveResourcesBean;
import com.xoms.front.model.res.RoleResourceBean;
import com.xoms.front.persist.dao.AccountDao;
import com.xoms.front.persist.dao.ResourceDao;
import com.xoms.front.service.AccountService;
import com.xoms.front.service.exception.ServiceException;
import com.xoms.util.MD5Util;
import com.xoms.util.RandomUtil;
import com.xoms.util.StringUtil;
import com.xoms.util.aliMessage.MessageUtil;

@Service
public class AccountServiceImpl implements AccountService {

	Logger logger = Logger.getLogger(this.getClass());

	@Autowired
	AccountDao accountImpl;

	@Autowired
	ResourceDao resourceImpl;

	@Autowired
	AccountCache accountCacheImpl;

	@Autowired
	ResourceCache resourceCacheImpl;

	@Override
	public RAccountLoginBean login(String phoneNum, String password) {
		// 切换至影院数据源
		DataSourceSwitcher.setDataSourceType(DataSourceSwitcher.DATA_SOURCE_XOMS);
		// 根据手机号查询账号是否存在
		AccountBean account = accountImpl.selectOneByPhone(phoneNum);

		if (account == null) {// 账户不存在
			throw new ServiceException("account_login_is_error");
		}

		if (account.getStatus() == 0) {// 账号被禁用
			throw new ServiceException("account_is_disabled");
		}

		if (account.getStatus() == 2) {// 账号已删除
			throw new ServiceException("account_is_delete");
		}

		String accId = account.getAccid();// 账号id
		String pwd = account.getPassword();// 账号密码
		// MD5加密密码
		password = MD5Util.sha256Hex(password);

		logger.info("password sha256Hex is:" + password);

		if (!password.equals(pwd)) {// 密码不正确
			throw new ServiceException("account_login_is_error");
		}
		if (accountImpl.updateLastLoginTime(accId) > 0) {// 更新用户上次登录时间
			// 将登录token存入缓存
			String token = accountCacheImpl.setToken(accId);
			// 返回登录账号对象
			RAccountLoginBean ra = new RAccountLoginBean();
			ra.setToken(token);
			ra.setAccId(accId);
			ra.setName(account.getName());
			ra.setIcon(account.getIcon());
			ra.setPhone(account.getPhoneNum());
			ra.setDepartment(account.getDepartment());
			ra.setDeptId(account.getDeptId());
			// 从缓存中获取 用户权限
			List<HaveResourcesBean> resources = resourceCacheImpl.getAccountResource(accId);
			if (null == resources || resources.isEmpty()) {// 缓存内无账号权限列表，查询账号角色
				// 获取账号角色id列表，从缓存获取角色对应权限，去重
				List<RoleResourceBean> roles = resourceImpl.selectRoleResouces2Account(accId);
				logger.info("account roles is" + JSON.toJSONString(roles));
				if (roles != null && !roles.isEmpty()) {
					resources = resourceCacheImpl.setAccountResource(accId, roles);
				}
			}
			logger.info("account resources is" + JSON.toJSONString(resources));
			if (resources != null && !resources.isEmpty()) {
				List<RHaveResourcesBean> res = new ArrayList<>();
				// 循环赋值
				for (HaveResourcesBean resource : resources) {
					RHaveResourcesBean rh = new RHaveResourcesBean();
					rh.setLevel(resource.getLevel());
					rh.setPid(resource.getPid());
					rh.setResourceName(resource.getResourceName());
					rh.setRid(resource.getRid());
					rh.setType(resource.getType());
					rh.setUrl(resource.getUrl());
					res.add(rh);
				}
				// 给用户设置权限列表
				ra.setResources(res);
			}
			logger.info("account is" + JSON.toJSONString(ra));
			return ra;
		}

		return null;
	}

	@Override
	public RAccountLoginBean getAccountByToken(String token) {
		// 获取移动端的token
		String accId = accountCacheImpl.getAccidByToken(token);
		logger.debug("get account accid by token:" + accId);
		if (StringUtil.isEmpty(accId)) {
			accId = "f6827c7482604efe80984d0d30399085";// 测试用
			// return null;
		}

		// 切换至影院数据源
		DataSourceSwitcher.setDataSourceType(DataSourceSwitcher.DATA_SOURCE_XOMS);
		AccountBean account = accountImpl.selectOneByAccid(accId);
		if (account == null) {// 账户不存在
			throw new ServiceException("account_login_is_error");
		}

		if (account.getStatus() == 0) {// 账号被禁用
			throw new ServiceException("account_is_disabled");
		}

		if (account.getStatus() == 2) {// 账号已删除
			throw new ServiceException("account_is_delete");
		}
		// 返回登录账号对象
		RAccountLoginBean ra = new RAccountLoginBean();
		ra.setToken(token);
		ra.setAccId(accId);
		ra.setName(account.getName());
		ra.setIcon(account.getIcon());
		ra.setPhone(account.getPhoneNum());
		ra.setDepartment(account.getDepartment());
		ra.setDeptId(account.getDeptId());
		// 从缓存中获取 用户权限
		List<HaveResourcesBean> resources = resourceCacheImpl.getAccountResource(accId);
		if (null == resources || resources.isEmpty()) {// 缓存内无账号权限列表，查询账号角色
			// 获取账号角色id列表，从缓存获取角色对应权限，去重
			List<RoleResourceBean> roles = resourceImpl.selectRoleResouces2Account(accId);
			logger.info("account roles is" + JSON.toJSONString(roles));
			if (roles != null && !roles.isEmpty()) {
				resources = resourceCacheImpl.setAccountResource(accId, roles);
			}
		}
		logger.info("account resources is" + JSON.toJSONString(resources));
		if (resources != null && !resources.isEmpty()) {
			List<RHaveResourcesBean> res = new ArrayList<>();
			// 循环赋值
			for (HaveResourcesBean resource : resources) {
				RHaveResourcesBean rh = new RHaveResourcesBean();
				rh.setLevel(resource.getLevel());
				rh.setPid(resource.getPid());
				rh.setResourceName(resource.getResourceName());
				rh.setRid(resource.getRid());
				rh.setType(resource.getType());
				rh.setUrl(resource.getUrl());
				res.add(rh);
			}
			// 给用户设置权限列表
			ra.setResources(res);
		}
		logger.info("account is" + JSON.toJSONString(ra));
		return ra;
	}

	@Override
	public boolean sendVCode(int type, String phone) throws Exception {

		// 切换至影院数据源
		DataSourceSwitcher.setDataSourceType(DataSourceSwitcher.DATA_SOURCE_XOMS);
		// type1：找回密码
		AccountBean account = accountImpl.selectOneByPhone(phone);
		if (type == 1) {// 找回密码，发送验证码，手机号没有注册
			if (account == null) {
				throw new ServiceException("account_fpwd_phone_is_not_exist");
			}
		}
		// 验证码15分钟内有效
		String vcode = accountCacheImpl.getVCode(type, phone);
		logger.debug("the phone vcode from cache is : " + vcode);
		if (StringUtil.isEmpty(vcode)) {
			vcode = RandomUtil.getRandomNum(4);
			logger.debug("the phone new vcode is : " + vcode);
			// 设置验证码
			accountCacheImpl.setVCode(type, phone, vcode);
		}

		// 发送验证码到手机号
		// 调用阿里接口发送短信
		MessageUtil.init(StringConstants.getInstance().getString("ali_msg_accessKeyId"),
				StringConstants.getInstance().getString("ali_msg_accessKeySecret"),
				StringConstants.getInstance().getString("ali_msg_signName"));
		SendSmsResponse response = MessageUtil.sendIdentifyingCode(phone, vcode);// 阿里云发送短信
		logger.info("Message=" + response.getMessage());
		return true;
	}

	@Override
	public RVertifyVCodeBean vertifyVCode(int type, String phone, String vcode) {
		// 切换至影院数据源
		DataSourceSwitcher.setDataSourceType(DataSourceSwitcher.DATA_SOURCE_XOMS);
		AccountBean account = accountImpl.selectOneByPhone(phone);
		if (type == 1) {// 找回密码
			if (account == null) {
				throw new ServiceException("account_fpwd_phone_is_not_exist");
			}
			// 获取内存验证码
			String tempCode = accountCacheImpl.getVCode(type, phone);
			if (tempCode == null) {// 验证码失效
				throw new ServiceException("account_fpwd_vcode_is_expire");
			}

			if (!vcode.equals(tempCode)) {// 验证码输入有误
				throw new ServiceException("account_fpwd_vcode_is_error");
			}

			String tempToken = accountCacheImpl.setTempToken2FindPassword(account.getAccid(), 5 * 60);// 临时token5分钟有效

			RVertifyVCodeBean rv = new RVertifyVCodeBean();
			rv.setTempToken(tempToken);

			return rv;
		}
		return null;
	}

	@Override
	public boolean findPassword(String tempToken, String pwd, String submitPwd) {
		// 切换至影院数据源
		DataSourceSwitcher.setDataSourceType(DataSourceSwitcher.DATA_SOURCE_XOMS);
		// 根据临时token获取账号id
		String accid = accountCacheImpl.getAccid2FindPasswordByTempToken(tempToken);
		if (accid == null) {
			throw new ServiceException("account_fpwd_tempToken_is_error");
		}
		// 根据账号id获取账号信息
		AccountBean account = accountImpl.selectOneByAccid(accid);
		if (account == null) {
			throw new ServiceException("account_fpwd_phone_is_not_exist");
		}
		// 设置新密码
		String np = MD5Util.sha256Hex(pwd);
		String sp = MD5Util.sha256Hex(submitPwd);

		if (!np.equals(sp)) {// 新密码、确认密码不一致
			throw new ServiceException("account_fpwd_pwd_is_not_same");
		}

		AccountBean temp = new AccountBean();
		temp.setAccid(accid);
		temp.setPassword(np);

		if (accountImpl.updatePwd(temp) > 0) {// 更新密码
			return true;
		}
		return false;
	}

	@Override
	public boolean updatePassword(AccountBean account, String oldPwd, String newPwd, String submitPwd) {
		// 切换至影院数据源
		DataSourceSwitcher.setDataSourceType(DataSourceSwitcher.DATA_SOURCE_XOMS);
		// 验证输入的密码是否正确
		String opwd = account.getPassword();
		logger.debug("the oldPwd is : " + opwd);

		if (StringUtil.isEmpty(oldPwd) || !MD5Util.sha256Hex(oldPwd).equals(opwd)) {// 输入密码有误
			throw new ServiceException("account_pwd_is_error");
		}

		// 验证两次密码是否一致
		if (StringUtil.isEmpty(newPwd) || !newPwd.equals(submitPwd)) {// 新密码、确认密码不一致
			throw new ServiceException("account_fpwd_pwd_is_not_same");
		}

		// 更新密码
		AccountBean temp = new AccountBean();
		temp.setAccid(account.getAccid());
		temp.setPassword(MD5Util.sha256Hex(newPwd));

		if (accountImpl.updatePwd(temp) > 0) {// 更新密码
			return true;
		}
		return false;
	}

}
